package com.tukez.tmdb.http
import java.util.concurrent.CountDownLatch
import java.util.concurrent.LinkedBlockingQueue
import java.util.LinkedList
import scala.collection.mutable.Queue
import org.joda.time.Duration
import java.util.concurrent.TimeUnit

class BarrierLatch(capacity: Int, countDowns: Int) {

  private val latches = Queue[Latch]()

  def countDown(): Unit = latches.synchronized {
    for (i <- 1 to capacity) {
      val latch = latches.find(_.isClosed) match {
        case Some(latch) => latch
        case None => {
          val latch = new Latch
          latches.enqueue(latch)
          latch
        }
      }
      latch.countDown()
    }
  }

  def await(timeout: Duration = new Duration(1000)) {
    var latch: Latch = null
    latches.synchronized {
      latch = latches.find(!_.used) match {
        case Some(latch) => latch
        case None => {
          val latch = new Latch
          latches.enqueue(latch)
          latch
        }
      }
      latch.use()
    }
    latch.await(timeout.getMillis)
  }

  private class Latch {

    private val latch = new CountDownLatch(countDowns)

    @volatile
    var countDownsLeft = countDowns

    @volatile
    var used = false

    def countDown() {
      latch.countDown()
      countDownsLeft -= 1
    }
    
    def isClosed = {
      countDownsLeft > 0
    }

    def use() {
      used = true
    }

    def await(timeout: Long) {
      latch.await(timeout, TimeUnit.MILLISECONDS)
    }
  }

}